# 整数数组 nums 按升序排列，数组中的值 互不相同 。
#  在传递给函数之前，nums 在预先未知的某个下标 k（0 <= k < nums.length）上进行了 旋转，使数组变为
#  [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]（下标 从 0 开始 计数）。
#  例如， [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
#  给你 旋转后 的数组 nums 和一个整数 target ，如果 nums 中存在这个目标值 target ，则返回它的下标，否则返回 -1 。
#
#  示例 1：
# 输入：nums = [4,5,6,7,0,1,2], target = 0
# 输出：4
#
#  示例 2：
# 输入：nums = [4,5,6,7,0,1,2], target = 3
# 输出：-1
#
#  示例 3：
# 输入：nums = [1], target = 0
# 输出：-1
from typing import List


class Solution:
    def search(self, nums: List[int], target: int) -> int:
        """
        变形的二分查找
        将数组从中间分开成左右两部分的时候，一定有一部分的数组是有序的:
        每次在有序的部分进行二分查找
        1.确定有序部分
            如果 nums[0] <= nums[mid] 则说明左半部分全部有序(nums[0] <= nums[mid]要取等是因为有可能二分到mid的下标为0)，此时:
                如果  nums[0] <= target  < nums[mid] 则下一步应该在区间[low, mid - 1]中尝试查找
                否则在区间[mid + 1, high]中尝试查找
            否则就是右半部分有序
                如果nums[mid] < target <= nums[high]，则下一步应该在区间[mid + 1, high]中尝试查找
                否则在区间[low, mid - 1]中尝试查找
        :param nums:
        :param target:
        :return:
        """
        low, high = 0, len(nums) - 1
        while low <= high:
            mid = low + ((high - low) >> 1)
            if nums[mid] == target:
                return mid
            if nums[low] <= nums[mid]:  # 左半段都是有序的
                if nums[low] <= target and target < nums[mid]:
                    high = mid - 1
                else:
                    low = mid + 1
            else:  # 右半段都是有序的
                if nums[mid] < target and target <= nums[high]:
                    low = mid + 1
                else:
                    high = mid - 1
        return -1


if __name__ == "__main__":
    nums = [4, 5, 6, 7, 0, 1, 2]
    target = 2
    nums = [1, 3]
    target = 1

    nums = [3, 1]
    target = 1

    print(Solution().search(nums, target))
